<?php

declare(strict_types=1);

namespace App\Middleware;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface as HttpResponse;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Hyperf\Utils\Context;
use Service\UserService\CashManagerService;
use Service\Code\Normal;
use Service\MessageService\WebApiRequestLogService;
use Hyperf\Contract\ConfigInterface;
use Hyperf\Di\Annotation\Inject;

class CashMiddleware implements MiddlewareInterface
{
    //需要排除登录控制器
    protected $except = [
        '/cash/v1/login',//登录控制器
        '/cash/v1/publics',//版本更新
        '/cash/v1/screen'
    ];
    
    /**
     * @var ContainerInterface
     */
    protected $container;
    
    /**
     * @var RequestInterface
     */
    protected $request;
    
    /**
     * @var HttpResponse
     */
    protected $response;
    
    /**
     * @Inject
     * @var ConfigInterface
     */
    protected $configInterface;
    public function __construct(ContainerInterface $container, HttpResponse $response, RequestInterface $request)
    {
        $this->container = $container;
        $this->response = $response;
        $this->request = $request;
    }

    /**
     * 处理中间介逻辑
     * {@inheritDoc}
     * @see \Psr\Http\Server\MiddlewareInterface::process($request, $handler)
     */
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        $rt_start = microtime(true);
        $url   = (string)$this->request->getUri();
        $parsedUrl = parse_url($url);
        $modules = \explode("/",$parsedUrl['path']);
        array_pop($modules);
        
        $except_url = \implode("/", $modules);
        $except_url = strtolower($except_url);
        
        $token = $this->request->header('token');
        $token = !empty($token) ? $token : $request->getAttribute('param');
        if( empty($token) && !in_array($except_url,$this->except) ) {
            return $this->response->json(Normal::returnCode(Normal::FAIL,"缺少token"),true);
        }
        
        if( !empty($token) && !in_array($except_url,$this->except)) 
        {
            //解密token
            $tokenvalue= CashManagerService::instance()->keyDecrypt($token);
            if( empty($tokenvalue) ) {
                return $this->response->json(Normal::returnCode(Normal::TOKEN_ERROR,"验证会话token解析失败，请稍微再试！"),true);
            }
            
            //查询管理账号数据
            $decodeData = @json_decode($tokenvalue,true);
            if( empty($decodeData['manager_id']) ) {
                return $this->response->json(Normal::returnCode(Normal::TOKEN_ERROR,"验证会话token.manager_id解析失败，请稍微再试！"),true);
            }
            
            $manager= CashManagerService::instance()->getCashUserInfo((int)$decodeData['manager_id']);
            if(empty($manager)){
                return $this->response->json(Normal::returnCode(Normal::TOKEN_ERROR,"token 错误"),true);
            }
            
            if( $manager['token'] != $token ) {
                return $this->response->json(Normal::returnCode(Normal::TOKEN_EXPIRED,"token 失效 请重新登录"),true);
            }
            
            $request = $request->withAttribute('manager_id',(int)$decodeData['manager_id']);
            $request = $request->withAttribute('cid',(int)$decodeData['cid']);
            $request = $request->withAttribute('mn_sid',(int)$decodeData['mn_sid']);
            $request = $request->withAttribute('sid',(int)$decodeData['sid']);
            $request = $request->withAttribute('casher_id',(int)$decodeData['casher_id']);
            $request = $request->withAttribute('manager_name',(string)$manager['name']);
            $this->configInterface->set('sid',(int)$decodeData['sid']);
        }
        
        //设置请求交给上下文request object
        Context::set(RequestInterface::class, $request);
        $response = $handler->handle($request);
        $json     = $response->getBody()->getContents();
        $response_data = @json_decode($json,true);        
        
        //接口tps 处理耗时
        $request_used_time = bcsub((string)microtime(true),(string)$rt_start,3);
        //body
        $body = $this->request->getParsedBody();
        //写入日志数组
        $logs = [
            'request_terminal'      => 2,
            'request_url_hash'      => md5($url),
            'request_url'           => $url,
            'request_method'        => $this->request->getMethod(),
            'request_parameters'    => json_encode($body,JSON_UNESCAPED_UNICODE),
            'request_used_time'     => $request_used_time,
            'request_ip'            => getIp(),
            'response_code'         => $response_data['code'],
            'response_msg'          => $response_data['msg'],
            'response_contents'     => json_encode($response_data,JSON_UNESCAPED_UNICODE),
            'request_time'          => time(),
        ];
        //发布日志队列
        WebApiRequestLogService::instance()->publishMsg($logs);
        return $this->response->json($response_data);
    }
}
